/** @file    NetworkProtocol.cpp
 *  @author  Alessandro Polo
 *  @version $Id: NetworkProtocol.cpp 2832 2010-08-02 22:53:46Z alex $
 *  @brief
 * File containing methods for the wosh::NetworkProtocol class.
 * The header for this class can be found in NetworkProtocol.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include <core/NetworkProtocol.h>

 #include <core/NetworkManager.h>
 #include <core/ObjectFactory.h>
 #include <core/BusManager.h>
 #include <core/MessageProcessingCommon.h>
 #include <core/MethodsCommon.h>
 #include <core/Utilities.h>
 #include <core/DataModels.h>
 #include <core/List.h>


using namespace std;
namespace wosh {

 WOSH_REGISTER_INTERFACE(wosh::NetworkProtocol, "wosh::Object", 0.66, _static_NetworkProtocol)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS

NetworkProtocol::NetworkProtocol()
	: Object( NetworkManager::getInstance() ) {
	Object::setName("NetworkProtocol", Utilities::randomLong() );
	this->listener = NULL;

	Log.setIndent( 3 );
	Log.setContext( "NetworkProtocol" );
	Log.setLevel( LOG_INFO );

	Log(LOG_DEBUG, " Settings Properties.." );
	Properties.set( _NetworkProtocol_KEY_ProtocolPrefix,"",	Permission(Permission::Read) );
	Properties.set( _NetworkProtocol_KEY_Priority,		0,	Permission::RW_RW_R__() );
	Properties.set( _NetworkProtocol_KEY_ServersCount,	-1, Permission(Permission::Read) );
	Properties.set( _NetworkProtocol_KEY_ClientsCount,	-1, Permission(Permission::Read) );
	Properties.updateObjectKeys(this);
	Properties.setPropertiesProviderListener(this);

	Log(LOG_DEBUG, " Registering Methods.." );

	MethodPropertyT::createMethods( &Methods, &Properties, &Log );

	MethodChT::createMethods( &Methods, this, &Properties, &Log );

	MethodList* mmListMethods = Methods.create<MethodList>( _METHOD_ListMethods, "List Methods", Permission(Permission::RX) );
	mmListMethods->setDataFieldExtractor( DataFieldExtractor<Method>::createFor< DataAdapterMapT<std::string,Method> >(Methods, "NetworkProtocol Methods") );

	MethodRequest* mmConnect = Methods.create<MethodRequest>( _NetworkProtocol_METHOD_connect, "connect", Permission::R_XR_XR__() );
	mmConnect->setMethod( this, (MethodRequestPtr)&NetworkProtocol::mmDoConnect );

	MethodRequest* mmListen = Methods.create<MethodRequest>( _NetworkProtocol_METHOD_listen, "listen", Permission::R_XR_XR__() );
	mmListen->setMethod( this, (MethodRequestPtr)&NetworkProtocol::mmDoListen );

 }

NetworkProtocol::~NetworkProtocol() {
 }

//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////// 

WRESULT NetworkProtocol::setListener( INetworkProtocolListener* ch_listener ) {
	 this->listener = ch_listener;
	 return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////// PROPERTY EVENTS

bool NetworkProtocol::updatingProperty( bool& , const Variant& , Property& , const PropertiesProvider* ) {
	return true;
 }

///////////////////////////////////////////////////////////////////////////////////////////// PROPERTY EVENTS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

Response* NetworkProtocol::mmDoConnect( const Request* request ) {
	if ( request == NULL ) return NULL;
	Variant proto_string;
	request->extractArguments(proto_string);
	if ( !proto_string.isStringNotEmpty() )
		return request->replyResponse(WRET_ERR_PARAM, "invalid protocol string");
	Log(LOG_VERBOSE, ":mmDoConnect(%s) : Calling connectChannel(asynch)..", proto_string.asString().c_str() );
	WRESULT ret = WRET_ERR_PARAM;
	ret = connectChannel( proto_string.asString(), 0 );
// ret = connectChannel( const std::vector<std::string>& protocolsAvailable, 0 ) = 0;
	return request->replyResponse(ret);
 }

Response* NetworkProtocol::mmDoListen( const Request* request ) {
	if ( request == NULL ) return NULL;
	Variant proto_string;
	request->extractArguments(proto_string);
	if ( !proto_string.isStringNotEmpty() )
		return request->replyResponse(WRET_ERR_PARAM, "invalid protocol string");
	Log(LOG_VERBOSE, ":mmDoConnect(%s) : Calling connectChannel(asynch)..", proto_string.asString().c_str() );
	WRESULT ret = WRET_ERR_PARAM;
	ret = listenChannel( proto_string.asString(), 0 );
	return request->replyResponse(ret);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

DataFieldCollector<NetworkProtocol>* NetworkProtocol::getDataFields() {
	DataFieldCollector<NetworkProtocol>* fields = new DataFieldCollector<NetworkProtocol>();
	fields->add<const std::string&, Variant>(&NetworkProtocol::getName, "Name", 0);
	fields->add<const char*,Variant>(&NetworkProtocol::getClassName, "Type", 1);
	fields->add<const char*,Variant>(&NetworkProtocol::getProtocolPrefix, "ProtocolPrefix", 2);
	fields->add<int,Variant>(&NetworkProtocol::getServersCount, "Servers", 3);
	fields->add<int,Variant>(&NetworkProtocol::getClientsCount, "Clients", 4);
	fields->add<const std::string&,Variant>(&NetworkProtocol::getEntityID, "EntityID", 5, false);
	fields->add<const URI&,URI>(&NetworkProtocol::getURI, "URI", 6, false);
	fields->add<const Permission&,Permission>(&NetworkProtocol::getPermission, "Permission", 7, false);
	return fields;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::NetworkProtocol_ListChanged, "wosh::Fact", 1.0, _static_NetworkProtocol_ListChanged )

NetworkProtocol_ListChanged::NetworkProtocol_ListChanged( const std::string& network_protocol_name, int action )
	: Fact( _NetworkProtocol_EVENT_ConnectionChanged ) {
	List* args = List::createFrom<Variant>( network_protocol_name, action );
	setData(args);
 }

std::string NetworkProtocol_ListChanged::getNetworkProtocolName() const {
	const Variant* var = getDataItem<Variant>(0);
	if ( var == NULL ) return "";
	if ( var->isString() ) return var->asString();
	return var->toString();
 }

int NetworkProtocol_ListChanged::getListAction() const {
	const Variant* var = getDataItem<Variant>(1);
	if ( var == NULL ) return 0;
	if ( var->isNumeric() ) return 0;
	return var->toInteger(0);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

}; // namespace wosh
